#include "../include/core/Executor.hpp"
#include "../include/command/CmderFactory.hpp"
#include <gtest/gtest.h>
#include <vector>
#include <stdexcept>
#include <string>

// 测试1：默认初始化状态
TEST(ExecutorTest, should_return_default_pose_given_no_init) {
    Executor executor;
    Pose actual = executor.getCurrentState();
    Pose expected = {0, 0, 'N'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
    EXPECT_FALSE(executor.IsAccelerated());
    EXPECT_FALSE(executor.IsReversed());
}

// 测试2：自定义初始化状态
TEST(ExecutorTest, should_return_custom_pose_given_init_with_valid_params) {
    Executor executor;
    executor.init(5, -3, 'W');
    Pose actual = executor.getCurrentState();
    Pose expected = {5, -3, 'W'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
    EXPECT_FALSE(executor.IsAccelerated());
    EXPECT_FALSE(executor.IsReversed());
}

// 测试3：移动指令M
TEST(ExecutorTest, should_move_correct_steps_given_command_M_and_heading) {
    {
        Executor executor;
        executor.init(2, 4, 'N');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {2, 5, 'N'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
    }

    {
        Executor executor;
        executor.init(2, 4, 'N');
        executor.executeCmd('F');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {2, 6, 'N'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
    }

    {
        Executor executor;
        executor.init(0, 0, 'E');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {1, 0, 'E'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
    }
}

// 测试4：左转指令L
TEST(ExecutorTest, should_turn_left_correctly_given_command_L) {
    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('L');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 0, 'W'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
        EXPECT_EQ(actual.heading, expected.heading);
    }

    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('F');
        executor.executeCmd('L');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 1, 'W'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
        EXPECT_EQ(actual.heading, expected.heading);
    }
}

// 测试5：右转指令R
TEST(ExecutorTest, should_turn_right_correctly_given_command_R) {
    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('R');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 0, 'E'};
        EXPECT_EQ(actual.heading, expected.heading);
    }

    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('F');
        executor.executeCmd('R');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 1, 'E'};
        EXPECT_EQ(actual.y, expected.y);
        EXPECT_EQ(actual.heading, expected.heading);
    }
}

// 测试6：加速指令F
TEST(ExecutorTest, should_toggle_accelerated_state_given_command_F) {
    Executor executor;
    EXPECT_FALSE(executor.IsAccelerated());
    executor.executeCmd('F');
    EXPECT_TRUE(executor.IsAccelerated());
    executor.executeCmd('F');
    EXPECT_FALSE(executor.IsAccelerated());
    executor.executeCmd('F');
    EXPECT_TRUE(executor.IsAccelerated());
}

// 测试7：批量指令（不含B）
TEST(ExecutorTest, should_execute_correctly_given_batch_commands) {
    Executor executor;
    std::vector<char> cmds = {'F', 'M', 'R', 'M', 'F', 'M'};
    executor.executeBatchCmds(cmds);
    Pose actual = executor.getCurrentState();
    Pose expected = {3, 3, 'E'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}

// 测试8：异常处理
TEST(ExecutorTest, should_throw_exception_given_invalid_cmd_or_heading) {
    {
        Executor executor;
        EXPECT_THROW(executor.executeCmd('X'), std::invalid_argument);
    }
    {
        Executor executor;
        EXPECT_THROW(executor.init(0, 0, 'X'), std::invalid_argument);
    }
}

// 测试9：倒车指令B（单独状态）
TEST(ExecutorTest, should_reverse_correctly_given_command_B_alone) {
    {
        Executor executor;
        executor.init(2, 4, 'N');
        executor.executeCmd('B');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {2, 3, 'N'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.y, expected.y);
    }

    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('B');
        executor.executeCmd('L');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 0, 'E'};
        EXPECT_EQ(actual.heading, expected.heading);
    }

    {
        Executor executor;
        executor.init(0, 0, 'N');
        executor.executeCmd('B');
        executor.executeCmd('B');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {0, 1, 'N'};
        EXPECT_EQ(actual.y, expected.y);
    }
}

// 测试10：B与F叠加状态
TEST(ExecutorTest, should_handle_correctly_given_B_and_F_overlap) {
    {
        Executor executor;
        executor.init(5, 5, 'E');
        executor.executeCmd('F');
        executor.executeCmd('B');
        executor.executeCmd('M');
        Pose actual = executor.getCurrentState();
        Pose expected = {3, 5, 'E'};
        EXPECT_EQ(actual.x, expected.x);
    }

    {
        Executor executor;
        executor.init(0, 0, 'E');
        executor.executeCmd('F');
        executor.executeCmd('B');
        executor.executeCmd('L');
        Pose actual = executor.getCurrentState();
        Pose expected = {-1, 0, 'S'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.heading, expected.heading);
    }

    {
        Executor executor;
        executor.init(0, 0, 'E');
        executor.executeCmd('F');
        executor.executeCmd('B');
        executor.executeCmd('R');
        Pose actual = executor.getCurrentState();
        Pose expected = {-1, 0, 'N'};
        EXPECT_EQ(actual.x, expected.x);
        EXPECT_EQ(actual.heading, expected.heading);
    }
}

// 测试11：批量指令含B
TEST(ExecutorTest, should_execute_correctly_given_batch_commands_with_B) {
    Executor executor;
    std::vector<char> cmds = {'B', 'F', 'M', 'R', 'B', 'M'};
    executor.init(10, 10, 'N');
    executor.executeBatchCmds(cmds);
    Pose actual = executor.getCurrentState();
    Pose expected = {8, 7, 'W'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}

// 测试12：TR正常状态
TEST(ExecutorTest, should_turn_round_correctly_given_TR_in_normal_state) {
    Executor executor;
    executor.init(0, 0, 'E');
    executor.executeBatchCmds("TR");
    Pose actual = executor.getCurrentState();
    Pose expected = {0, 1, 'W'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}

// 测试13：TR加速状态
TEST(ExecutorTest, should_turn_round_correctly_given_TR_in_fast_state) {
    Executor executor;
    executor.init(0, 0, 'E');
    executor.executeCmd('F');
    executor.executeBatchCmds("TR");
    Pose actual = executor.getCurrentState();
    Pose expected = {1, 1, 'W'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}

// 测试14：TR倒车状态
TEST(ExecutorTest, should_ignore_TR_given_TR_in_reversed_state) {
    Executor executor;
    executor.init(0, 0, 'E');
    executor.executeCmd('B');
    executor.executeBatchCmds("TR");
    Pose actual = executor.getCurrentState();
    Pose expected = {0, 0, 'E'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}

// 测试15：TR与其他指令混合
TEST(ExecutorTest, should_execute_correctly_given_mixed_cmds_with_TR) {
    Executor executor;
    executor.init(2, 3, 'N');
    executor.executeBatchCmds("FTRM");
    Pose actual = executor.getCurrentState();
    Pose expected = {1, 2, 'S'};
    EXPECT_EQ(actual.x, expected.x);
    EXPECT_EQ(actual.y, expected.y);
    EXPECT_EQ(actual.heading, expected.heading);
}